<template>
  <view class="switch-box">
    <view
      @click="toggle"
      class="custom-switch"
      :class="{ 'custom-switch--disabled': disabled }"
      :style="{
        width: 2 * size + 'px',
        height: switchHeight,
        borderRadius: size + 'px',
        backgroundColor: currentValue === activeValue ? activeColor : inactiveColor,
      }"
    >
      <view
        class="custom-switch__circle"
        :style="{
          width: size + 'px',
          height: size + 'px',
          transform: currentValue === activeValue ? `translateX(${size}px)` : `translateX(0)`,
        }"
      ></view>
    </view>
    <slot></slot>
  </view>
</template>

<script>
  export default {
    props: {
      value: {
        type: [String, Number, Boolean],
        default: false,
      },
      activeColor: {
        type: String,
        default: '#3072F6',
      },
      inactiveColor: {
        type: String,
        default: '#8799a3',
      },
      size: {
        type: Number,
        default: 24,
      },
      disabled: {
        type: Boolean,
        default: false,
      },
      activeValue: {
        type: [String, Number, Boolean],
        default: true,
      },
      inactiveValue: {
        type: [String, Number, Boolean],
        default: false,
      },
      beforeChange: {
        type: Function,
        default: null,
      },
      extraData: null,
      contextLevel: {
        type: Number,
        default: 1,
      },
    },
    computed: {
      switchHeight() {
        // #ifdef APP-NVUE
        return this.size + 2 + 'px'
        // #endif
        // #ifndef APP-NVUE
        return this.size + 'px'
        // #endif
      },
    },
    watch: {
      value: {
        immediate: true,
        handler(value) {
          this.currentValue = value
        },
      },
    },
    data() {
      return {
        currentValue: false,
      }
    },
    methods: {
      toggle() {
        if (!this.disabled) {
          if (this.beforeChange && typeof this.beforeChange === 'function') {
            let context = this
            for (let i = 0; i < this.contextLevel; i++) {
              context = context.$options.parent
            }
            const result = this.beforeChange(
              this.currentValue === this.activeValue ? this.inactiveValue : this.activeValue,
              this.extraData,
              context
            )
            if (typeof result === 'object') {
              result
                .then(() => {
                  this.toggleValue()
                })
                .catch(() => {})
            } else if (typeof result === 'boolean' && result) {
              this.toggleValue()
            }
          } else {
            this.toggleValue()
          }
        }
      },
      toggleValue() {
        this.currentValue = this.currentValue === this.activeValue ? this.inactiveValue : this.activeValue
        this.$emit('upate:modelValue', this.currentValue)
        this.$emit('change', this.currentValue)
      },
    },
  }
</script>

<style lang="scss" scoped>
  .switch-box {
    display: flex;
    align-items: center;
  }
  .custom-switch {
    position: relative;
    border-width: 1px;
    border-color: rgba(0, 0, 0, 0.1);
    border-style: solid;
    transition: background-color 0.3s;
    /* #ifndef APP-NVUE */
    box-sizing: content-box;
    /* #endif */
  }

  .custom-switch--disabled {
    opacity: 0.3;
  }

  .custom-switch__circle {
    position: absolute;
    left: 0;
    top: 0;
    background-color: #fff;
    border-radius: 50%;
    /* #ifndef APP-NVUE */
    box-shadow: 0 3px 1px 0 rgba(0, 0, 0, 0.05), 0 2px 2px 0 rgba(0, 0, 0, 0.1), 0 3px 3px 0 rgba(0, 0, 0, 0.05);
    /* #endif */
    /* #ifdef APP-NVUE */
    box-shadow: 1px 0 0px 0 rgba(0, 0, 0, 0.05);
    /* #endif */
    transition: transform 0.3s;
  }
</style>
